# Author: dolphin
# https://github.com/Dolphin4mi/zhihuBlogCopyer
# copy all the zhihu's blog into a markdown text,and translate the equations to the 'tex'
# Usage:
# 	1. copy all the content of the blog to a text file '.txt' or '.md'
# 	2. run this code with the filename = 'filename.txt' or 'filename.md'
# 	3. modify some backslash error
import os
import re
import sys
import time
import urllib
import urllib.request
from urllib.parse import unquote


def read_md_file(md_name):
    print('正在读入', md_name, '....')
    f = open(md_name, 'r+', encoding="utf-8")
    lines = f.readlines()
    f.close()
    print('读入完毕', md_name, '....')
    return lines


# 重写公式
def construct_equation(lines):
    # error_global全局错误描述
    global error_global

    # 构造字典，用来解码url
    key = []
    for i in range(16 * 16):
        key.append("%" + str(hex(i))[2:4].rjust(2, '0').upper())

    # 处理每一行
    # 先去除公式表达中无用的‘+’运算符
    for lineLoc in range(len(lines)):
        lines[lineLoc] = lines[lineLoc].replace('+', ' ')
    for lineloc in range(len(lines)):
        line = str(lines[lineloc])
        print(lineloc)
        while "![[公式]]" in line:
            startkuohaoLoc = line.find("![[公式]]")
            line = line.replace("![[公式]](https://www.zhihu.com/equation?tex=", "$", 1)

            # 匹配括号
            countkuohao = 1
            endkouhaoLoc = startkuohaoLoc
            while (countkuohao != 0):
                if line[endkouhaoLoc] == ")":  # 如果是右括号，则记数减1
                    countkuohao -= 1
                if line[endkouhaoLoc] == "(":
                    countkuohao += 1  # 如果是左括号，记数加1
                endkouhaoLoc += 1
            line = list(line)
            line[endkouhaoLoc - 1] = "$"

            line = "".join(line)
            # line = line.replace('+', ' ')

            # for i in range(len(key)):
            #     while (key[i] in line[startkuohaoLoc:endkouhaoLoc]):
            shorttxt = line[startkuohaoLoc:endkouhaoLoc]
            shorttex = unquote(shorttxt)  # 解码
            len_decreased = len(shorttxt) - len(shorttex)
            # line = line[:startkuohaoLoc] + line[startkuohaoLoc:endkouhaoLoc].replace(key[i], value[i], 1) + line[endkouhaoLoc:]
            line = line[:startkuohaoLoc] + shorttex + line[endkouhaoLoc:]
            endkouhaoLoc -= len_decreased

        while ('$ ' in line):
            startLoc = line.find('$ ')
            line = line[:startLoc] + '$' + line[startLoc + 2:]
        lines[lineloc] = line

    # 调整整体结构
    for lineloc in range(len(lines)):
        if lineloc != 0:
            oldline = line
        line = str(lines[lineloc])
        # 当这一行是一个段内公式时，则调整为$$\n...\n$$
        if lineloc != 0 and oldline[len(oldline) - 1] == '\n' and line[0] == '$' and line[len(line) - 2] == '$':
            line = '$$\n' + line[1:-2] + '\n$$\n'
            # line = line.replace('$', "$$")
        lines[lineloc] = line
    return lines


def requestImg(url, workpath):
    global error_global
    img_src = url
    try:
        filepath, _ = urllib.request.urlretrieve(url=img_src, filename=workpath)
    except:
        print('保存图片失败url=', url)
        error_global = 1


# 下载图片的函数
def download_img(md_name, lines):
    # 匹配图片url
    print('正在下载图片....')
    reg = r'\(https://pic.*?\.(jpg|png|gif|jpeg|bmp)+.*?\)'  # 其中的问号是最短匹配，适用于每行存在多个url图片
    # reg = re.compile(r'\(https://.*?\.(jpg|png|gif|jpeg|bmp)+.*?\)')  # 其中的问号是最短匹配，适用于每行存在多个url图片
    # 保存文件夹
    # savepath = md_name[:-3] + '.assets'
    savepath = '1.assets'
    if not os.path.exists(savepath):
        os.makedirs(savepath)
    # 下载图片
    imgcount = 0
    for lineloc in range(len(lines)):
        line = lines[lineloc]
        while re.search(reg, line):
            match_loc = re.search(reg, line).span()
            url = line[match_loc[0] + 1: match_loc[1] - 1]
            from urllib.parse import urlsplit
            imgname = os.path.join(savepath, os.path.basename(urlsplit(url).path))
            requestImg(url, imgname)
            imgcount += 1
            print('下载第', imgcount, '张图片', imgname)
            line = line[:match_loc[0] + 1] + imgname + ')' + line[match_loc[1]:]
        lines[lineloc] = line
    return lines


# 更改引用的“> ”为“背景色”
def changequote(lines):
    for lineloc in range(len(lines)):  # 处理每一行
        line = lines[lineloc]
        if line[:2] == "> ":  # 如果是quote的第一行，则开始处理
            line = "<table><tr><td bgcolor=LightGray>\n" + line[2:]  # 添加表头
            lines[lineloc] = line
            for bl in range(lineloc, len(lines)):
                if (bl + 1) < len(lines) and lines[bl + 1][:2] == '> ':  # 如果未超出文末，而且还是一个块的内容，处理此行，并在上一行增加换行<br\>
                    lines[bl + 1] = lines[bl + 1][2:]
                    lines[bl] = lines[bl][:-1] + '</br>'
                else:  # 如果不是块内容了，就在上一行加入块结束了标志
                    lines[bl] = lines[bl][:-1] + '</br>' + '</td></tr></table>' + '\n'
                    break
    print("已经将引用的“> ”为“背景色”")
    return lines


# 行内公式变蓝
def math2Bule(lines):
    for lineloc in range(len(lines)):  # 处理每一行
        line = lines[lineloc]
        
        startBlockMath = 0
        if line[:2].find('$$')!=-1: # 如果不是行内公式，就不处理,并查找块公式的结束位置
            if startBlockMath==0:  # 如果是块公式的开始，则记录开始，
                startBlockMath = 1
            else:  #  如果是块公式的结束,则块处理完成
                startBlockMath = 0
            continue
        if line.find('$')!=-1: # 如果有行内公式
            end = 0
            while end<=len(line):
                # print(len(line))
                # print("end=",end)
                Startdollar = end + line[end:].find('$')+1
                # print(line[Startdollar:])
                Enddollar = Startdollar+1 + line[Startdollar+1:].find('$')
                # print(line[Startdollar:Enddollar])
                line = line[:Startdollar] + '\\textcolor{blue}{' + line[Startdollar:Enddollar] + '}' +line[Enddollar:]
                # print(line)
                end = Enddollar+19
                if line[end:].find('$')==-1:
                    break
            lines[lineloc] = line
    return lines
        # for Startdollar in range(len(line)):
        #     if Startdollar+1>len(line) and line[Startdollar]=='$' and line[Startdollar+1]!='$':
        #         match_loc = re.search(reg, line).span()
        # print(match_loc)
        
        
#块公式变蓝
def blockmath2blue(lines):
    startBlockMath = 0
    for lineloc in range(len(lines)):
        print(lineloc)
        line = lines[lineloc]
        if line[:2].find('$$')!=-1: # 如果是块公式，记录,并查找块公式的结束位置
            if startBlockMath==0:  # 如果是块公式的开始，则记录开始，
                line = line+'\\textcolor{blue}{\n'
                startBlockMath = 1
            else:  #  如果是块公式的结束,则块处理完成
                line = '}\n' + line
                startBlockMath = 0
        lines[lineloc] = line
    return lines
        


# 写文件
def write_md_file(md_name, lines):
    global error_global
    f = open(md_name, 'w', encoding="utf-8")
    f.writelines(lines)
    f.close()
    if 0 == error_global:
        print('\033[32m处理完成，没有出错哦0\033[0m')
    else:
        print('\033[32m处理有问题，sorry\033[0m')
        time.sleep(3)


if __name__ == "__main__":
    global error_global
    error_global = 0
    md_name = sys.argv[1]
    # print(sys.argv)
    
    if '-h' in sys.argv or '--help' in sys.argv:
        print('python zhihuBlogCopyer.py [consequ] [downimg] [math2blue] [blockmath2blue]')
    
    if 'consequ' in sys.argv:
        lines = read_md_file(md_name)
        lines = construct_equation(lines)
        write_md_file(md_name, lines)
    
    if 'downimg' in sys.argv:
        lines = read_md_file(md_name)
        lines = download_img(md_name, lines)
        write_md_file(md_name, lines)

    if 'math2blue' in sys.argv:
        lines = read_md_file(md_name)
        lines = math2Bule(lines)
        write_md_file(md_name, lines)

    if 'blockmath2blue' in sys.argv:
        lines = read_md_file(md_name)
        lines = blockmath2blue(lines)
        write_md_file(md_name, lines)
    

